package com.willian.andrappfw.network;

import android.app.Activity;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import android.app.Dialog;

import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.observers.DisposableObserver;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.Observable;

import java.lang.ref.WeakReference;
import com.willian.andrappfw.bean.VersionBean;


public class WRequest<T> {

    private WeakReference<RequestContext> mRequestReference;
    private final Observable<T> mObservable;
    private final Callback<T> mCallback;
    private final DisposableObserver<T> mDisposable;

    public WRequest(@Nullable RequestContext requestContext, @NonNull Observable<T> observable, @Nullable Callback<T> callback) {
        this(observable, callback);
        if (requestContext != null) {
            this.mRequestReference = new WeakReference(requestContext);
        }
    }

    public WRequest(@NonNull Observable<T> observable, @Nullable Callback<T> callback) {
        this.mObservable = observable;
        this.mCallback = callback;
        this.mDisposable = this.getDisposable();
    }

    public DisposableObserver<T> getDisposable() {
        return new DisposableObserver<T>() {
            protected void onStart() {
                if (WRequest.this.mRequestReference != null && WRequest.this.mRequestReference.get() != null) {
                    ((RequestContext) WRequest.this.mRequestReference.get()).addRequest(WRequest.this);
                }

                if (WRequest.this.mCallback != null) {
                    WRequest.this.mCallback.onStart();
                }
            }

            public void onNext(T response) {
                if (WRequest.this.mCallback != null) {
                    WRequest.this.mCallback.onSuccess(response);
                }
            }

            public void onError(Throwable e) {
                if (WRequest.this.mCallback != null) {
                    WRequest.this.mCallback.onError(e);
                    WRequest.this.mCallback.onEnd();
                }

                if (WRequest.this.mRequestReference != null && WRequest.this.mRequestReference.get() != null) {
                    ((RequestContext) WRequest.this.mRequestReference.get()).removeRequest(WRequest.this);
                }
            }

            public void onComplete() {
                if (WRequest.this.mCallback != null) {
                    WRequest.this.mCallback.onEnd();
                }

                if (WRequest.this.mRequestReference != null && WRequest.this.mRequestReference.get() != null) {
                    ((RequestContext) WRequest.this.mRequestReference.get()).removeRequest(WRequest.this);
                }
            }
        };
    }

    public WRequest(@NonNull Observable<T> observable) {
        this(observable, (WBaseCallback)null);
    }

    public void enqueue() {
        this.mObservable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(this.mDisposable);
    }

    public T excute() {
        try {
            return this.mObservable.blockingFirst();
        } catch (Exception var2) {
            return null;
        }
    }

    public void cancel() {
        this.mDisposable.dispose();
    }

    public static class Builder<T> {
        private RequestContext requestContext;
        private Observable<T> observable;
        private Callback<T> callback;
        private Dialog dialog;
        private boolean cancelable;

        public Builder() {
        }

        public WRequest.Builder<T> with(@Nullable RequestContext requestContext) {
            this.requestContext = requestContext;
            return this;
        }

        public WRequest.Builder<T> setObservable(Observable<T> observable) {
            this.observable = observable;
            return this;
        }

        public WRequest.Builder<T> setCallback(@Nullable Callback<T> callback) {
            this.callback = callback;
            return this;
        }

        public WRequest.Builder<T> setLoadingDialog(@NonNull Dialog dialog, boolean cancelable) {
            this.dialog = dialog;
            this.cancelable = cancelable;
            return this;
        }

        public WRequest.Builder<T> setLoadingDialog(@NonNull Dialog dialog) {
            return this.setLoadingDialog(dialog, true);
        }

        public WRequest<T> build() {
            if (this.dialog != null) {
                this.callback.setProgressDialog(this.dialog);
            }

            WRequest<T> WRequest = new WRequest(this.requestContext, this.observable, this.callback);
            if (this.dialog != null) {
                this.dialog.setOnCancelListener((dialog) -> {
                    this.onDialogDisappeared(WRequest);
                });
                this.dialog.setOnDismissListener((dialog) -> {
                    this.onDialogDisappeared(WRequest);
                });
            }

            return WRequest;
        }

        private void onDialogDisappeared(WRequest WRequest) {
            if (WRequest != null && this.dialog != null) {
                if (this.cancelable) {
                    if (this.requestContext != null) {
                        this.requestContext.removeRequest(WRequest);
                    }

                    WRequest.cancel();
                } else if (this.dialog.getContext() instanceof Activity) {
                    ((Activity)this.dialog.getContext()).finish();
                }

            }
        }
    }
}
